[<<Previous Entry]
[^^Up^^]
[Next Entry>>]
[Menu]
[About The Guide]
INTERFACING WITH C
Clipper supports user-defined functions written in C through the Extend
System. This is a somewhat higher level interface system than the
usual CALLs, in that you use specialized functions for both passing
parameters to and from the routine.
These functions reside in the Clipper library. Your C routine must
declare them by including EXTEND.H. This file contains the program
declarations and macro definitions necessary to write user-defined
functions in C.
C extend functions must now be defined using the CLIPPER macro or
declaring the function "void pascal."
Receiving Parameters in C
The concept of C formal parameters disappears at this point. All
parameters may be accessed using the _par() functions. Therefore, all C
functions accessed through the Extend System are declared up with no
formal parameters.
Returning Values From C
The _ret() are used to return values back to Clipper. Each function,
by definition, can return only one value. The choice of which _ret()
function you use depends on the data type being returned.
Sample C Functions
Once you compute the value you want to return, pass it to the
appropriate _ret() function and it becomes the function return value.
It is still, however, necessary to execute a C return. _ret() functions
do not pass control back to Clipper.
Here is a shell of a typical Clipper user defined function written in
C:
CLIPPER <function_name>()
/* formal C parameters omitted */
{
<declarations of local variables>
if (<parameters are valid>)
{
<code to execute>
}
else
{
<code to execute for undefined parameters>
return;
}
}
In Clipper:
DECLARE arr[3]
arr[1] = "Devorah"
arr[2] = 456.56
arr[3] = CTOD("09/01/87")
Arrfunc(arr)
In C:
#include "extend.h" /* Declare Extend System */
#include "stdio.h" /* standard io library */
#include "math.h" /* standard math libaray */
CLIPPER arrfunc() /* specify CLIPPER */
/* macro to define function */
{
int i;
for (x = 1; x <= 3; ++x)
{
/* string variables */
if (_parinfa(1, x) == CHARACTER)
{
cprintf("%s\n", _parc(1, x));
}
/* integer or floating point */
if (_parinfa(1,X) == NUMERIC)
{
cprintf("%f\n", _parnd(1, x));
}
else
/* dates */
if (_parinfa(1, x) == DATE)
{
cprintf("%s\n", _pards(1, i));
}
}
_ret();
}
Note: The use of cprintf() above is for demonstration purposes only.
We recommend that all terminal I/O be done through Clipper.
Compiling and Linking Your C Code
To compile a Microsoft C 5.0 routine that can be MS-linked with Clipper
Summer '87:
CL /c /AL /Zl /Oalt /FPa /Gs <filename>.c
where:
CL = the compiler command
/c = compile without linking
/AL = set program configuration for (L)arge model
/Zl = remove default (l)ibrary-search records from
object file
/Oalt = control optimization
where:
a = relax alias checking
l = enable loop optimization
t = favor execution speed
/FPa = floating point (a)lternate library
/Gs = remove calls to (s)tack-checking routine
Predefined C Macros
To simplify the syntax and make the code more readable, Extend.h sets
up several "parameter check" macros used in the if statements in
Extendc.c for parameter checking. The following is a table of macros
that provide a more convenient way of parameter validation:
#defines in Extend.h
Type Returns
-------------------------
undefined = UNDEF
character = CHARACTER
numeric = NUMERIC
logical = LOGICAL
date = DATE
by reference = MPTR /* or'ed with type when passed by reference */
memo = MEMO
array = ARRAY
Predefined C Interface Macros
EXTEND.H Macro Defined as
-------------------------------
PCOUNT (_parinfo(0))
ISCHAR(order) (_parinfo(order) & CHARACTER)
ISNUM(order) (_parinfo(order) & NUMERIC)
ISLOG(order) (_parinfo(order) & LOGICAL)
ISDATE(order) (_parinfo(order) & DATE)
ISMEMO(order) (_parinfo(order) & MEMO)
ISBYREF(order) (_parinfo(order) & MPTR)
ISARRAY(order) (_parinfo(order) & ARRAY)
ALENGTH(order) (_parinfa(order, 0))
Within the user-defined function, you can use the PCOUNT macro and any
of the IS<type> macros to determine how many parameters were passed and
their type. This enables you to validate parameters insuring the
correct number and type passed. It additionally allows you to pass
variable numbers of parameters of various types.
Reference - Extend System C Interface Functions
-----------------------------------------------
_exmback()
Free allocated memory
Syntax Usage:
#include <extend.h>
void *_exmback(pointer, bytes)
unsigned char *pointer; Pointer from _exmgrab()
unsigned int bytes; Size passed to _exmgrab()
Description:
_exmback() releases the memory allocated by _exmgrab().
Note that the same pointer and size used in _exmgrab must be
passed as parameters.
Example:
size = 512
buff = _exmgrab(size) /* allocate memory */
if (buff) /* if successful (!null) */
check = TRUE;
.
.
.
if (check)
_exmback(buff, size); /* deallocate memory */
_exmgrab()
Allocate memory
Syntax Usage:
#include <extend.h>
unsigned char *_exmgrab(bytes)
unsigned int bytes; Requested amount of memory
Description:
_exmgrab() allocates an amount of memory in bytes. If
successful, it returns a char pointer to the allocated space in
memory; otherwise, it returns NULL.
Example:
size = 512
buff = _exmgrab(size) /* allocate memory */
if (buff) /* if successful (!null) */
check = TRUE;
_parc()
Passes pointer to Clipper character string
Syntax Usage:
#include <extend.h>
char *_parc(order, index)
int order; Placement in actual parameter list
int index; Array element index
Description:
_parc() is used for getting a character parameter from Clipper.
If passed by value the copy is char *. If passed by reference,
you are acting on actual Clipper data.
_parclen()
Length of character string
Syntax Usage:
#include <extend.h>
int _parclen(order, index)
int order; Placement in actual parameter list
int index; Array element index
Description:
_parclen() returns the length of a given string. It is used
primarily with respect to CHR(0). This has two uses:
Check for the length of a string with embedded
CHR(0)s in it.
Get the length of a string without counting the
null terminator.
_parcsiz()
Allocated size of a character string
Syntax Usage:
#include <extend.h>
int _parcsiz(order, index)
int order; Placement in actual parameter list
int index; Array element index
Description:
_parcsiz() returns the number of bytes in memory allocated for
the specified string including the null terminator. Note that
_parsize() returns zero for constants, e.g. DO <process> WITH
"ABC".
_pards()
Passes character pointer to Clipper date
Syntax Usage:
#include <extend.h>
char *_pards(order, index)
int order; Placement in actual parameter list
int index; Array element index
Description:
_pards() gets a date parameter from Clipper and returns a char *
in the form YYYYMMDD. Note that there is only one _pards()
pointer on the stack and therefore you must strcopy() the result
to a variable. You cannot simply pass the pointer.
_parinfa()
Parameter type-checking of array elements
Syntax Usage:
#include <extend.h>
int _parinfa(order, index)
int order; Placement of the array in parameter
list
int index; Array element index
Description:
_parinfa() returns type of an array element and is used for
parameter type-checking. Since Clipper arrays can have mixed
type elements, each one has to be type-checked before they can
be used. Note that _parinfa(<n>, 0) returns the number of array
elements.
Example:
The following example, arrfunc(), takes an array defined
in Clipper and displays all the elements formatted according to
data type to the console.
In Clipper:
DECLARE array[2]
array[1] = "Devorah"
array[2] = 456.56
ArrFunc(array)
In C:
for (x = 1; x <= _parinfa(1, 0); ++x)
{ /* string variables */
if (_parinfa(1, x) == CHARACTER)
{
cprintf("%s\n", _parc(1, x));
}
/* integer or floating point */
if (_parinfa(1, x) == NUMERIC)
{
cprintf("%f\n", _parnd(1, x));
}
}
_parinfo()
Parameter type checking
Syntax Usage:
#include <extend.h>
int _parinfo(order)
int order; Placement in list of
parameters to type-check
Description:
_parinfo() is used to test the type of a passed parameter.
_parinfo(0) returns the number of parameters passed and
_parinfo(<n>) returns the type of parameter <n> where <n> is the
position in the parameter list. The value returned is one the
following:
/* _parinfo types from extend.h*/
#define UNDEF 0
#define CHARACTER 1
#define NUMERIC 2
#define LOGICAL 4
#define DATE 8
#define ALIAS 16
#define MPTR 32 /* or'ed with type when passed by reference */
#define MEMO 65
#define WORD 128
#define ARRAY 512
Example:
The following user-defined C function, cfunc(), recieves four
parameters from Clipper, a character type, a numeric, a logical,
and a date; defines the C variables to receive the values, then
validates the parameters:
CLIPPER cfunc() /* no formal parameters */
{
char *parm1;
double parm2;
int parm3; /* logical is declared as int */
char *parm4; /* date declared as char (YYYYMMDD) */
if (PCOUNT == 4 && ISCHAR(1) && ISNUM(2) && ISLOG(3) && ISDATE(4))
{
<code to execute parameters valid>
}
else
{
<code to execute parameters invalid>
}
}
_parl()
Passes Clipper logical to int
Syntax Usage:
#include <extend.h>
int _parl(order, index)
int order; Placement in actual parameter list
int index; Array element index
Description:
_parl() gets a logical parameter from Clipper and converts it to
int where (1 = .T. and 2 = .F.).
_parnd()
Passes a Clipper numeric to double
Syntax Usage:
#include <extend.h>
double _parnd(order, index)
int order; Placement in actual parameter list
int index; Array element index
Description:
_parnd() gets a numeric parameter from Clipper and converting it
to double.
_parni()
Passes Clipper numeric to int
Syntax Usage:
#include <extend.h>
int _parni(order, index)
int order; Placement in actual parameter list
int index; Array element index
Description:
_parni() gets a numeric parameter from Clipper converting it to
int.
_parnl()
Passes Clipper numeric to long
Syntax Usage:
#include <extend.h>
long _parnl(order, index)
int order; Placement in actual parameter list
int index; Array element index
Description:
_parnl() gets a numeric parameter from Clipper converting it to
long.
_ret()
Return to Clipper
Syntax Usage:
#include <extend.h>
void _ret(void)
Description:
_ret() has no Clipper return value. This is useful so you can
execute a C function using the DO command as if it were a
Clipper procedure.
_retc()
Pass a character string to Clipper
Syntax Usage:
#include <extend.h>
void _retc(string)
char *string; Pointer to return string
Description:
_retc() returns the char* to Clipper for the character string
you want to pass back to your application program.
_retclen()
Pass the length of a string to Clipper
Syntax Usage:
#include <extend.h>
void _retclen(string, int)
char *string; Character string to return the length of
int int; Position in string to start the count
Description:
_retclen() returns the logical length of a string including
embedded CHR(0)s.
_retds()
Pass a date string to a Clipper date
Syntax Usage:
#include <extend.h>
void _retds(string)
char *string; Date string in the form (YYYYMMDD)
Description:
_retds() passes to Clipper as date type a char* to a string in
the form YYYYMMDD.
_retl()
Pass an int to a Clipper logical
Syntax Usage:
#include <extend.h>
void _retl(flag)
int flag; Boolean value
Description:
_retl() passes an int to Clipper as a logical value, where 1 is
true (.T.) and 0 is false (.F.).
_retnd()
Pass a double to a Clipper numeric
Syntax Usage:
#include <extend.h>
void _retnd(x);
double x; Numeric expression
Description:
_retnd() passes a double to Clipper as numeric type.
_retni()
Pass an int to a Clipper numeric
Syntax Usage:
#include <extend.h>
void _retni(n)
int n; Numeric expression
Description:
_retni() passes an int to Clipper as a numeric integer.
_retnl()
Pass a long to a Clipper numeric
Syntax Usage:
#include <extend.h>
void _retnl(n)
long n; Long numeric expression
Description:
_retnl() passes a long integer to Clipper as numeric type.
This page created by ng2html v1.05, the Norton guide to HTML conversion utility.
Written by Dave Pearson